package com.stone.starter.redis.client;

import com.stone.starter.redis.strategy.RedisShardingStrategy;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * Redis实例工厂
 *
 * @author Mr_wenpan@163.com 2021/07/17 11:14 下午
 */
public class RedisShardingClient {
    /**
     * redis连接工厂集合，key为实例名称，value为该实例对应的连接工厂
     */
    private final Map<String, RedisConnectionFactory> redisConnectionFactories;
    /**
     * redisTemplate集合，用户保存每个Redis实例对应的redisTemplate，项目中key-value的序列化方式默认采用string类型
     * key ： 对应着实例的名称，value ：对应着该实例的redisTemplate
     */
    private final Map<String, StringRedisTemplate> redisTemplates;

    public RedisShardingClient() {
        redisConnectionFactories = new ConcurrentHashMap<>();
        redisTemplates = new ConcurrentHashMap<>();
    }

    public Map<String, RedisConnectionFactory> getRedisConnectionFactories() {
        return redisConnectionFactories;
    }

    public Map<String, StringRedisTemplate> getRedisTemplates() {
        return redisTemplates;
    }

    public void addRedisConnectionFactories(String instanceName, RedisConnectionFactory redisConnectionFactory) {
        redisConnectionFactories.put(StringUtils.lowerCase(instanceName), redisConnectionFactory);
    }

    public void addRedisTemplates(String instanceName, StringRedisTemplate redisTemplates) {
        this.redisTemplates.put(StringUtils.lowerCase(instanceName), redisTemplates);
    }

    public <T> StringRedisTemplate getRedisTemplate(RedisShardingStrategy<T> shardingStrategy, T strategyCondition) {
        // 根据分片策略获取对应的Redis实例名称
        String redisInstanceName = shardingStrategy.redisShardingInstance(strategyCondition);
        return redisTemplates.get(StringUtils.lowerCase(redisInstanceName));
    }

    public <T> RedisConnectionFactory getRedisConnectionFactory(RedisShardingStrategy<T> shardingStrategy, T strategyCondition) {
        // 根据分片策略获取对应的Redis实例名称
        String redisInstanceName = shardingStrategy.redisShardingInstance(strategyCondition);
        // 获取对应实例的连接工厂
        return redisConnectionFactories.get(StringUtils.lowerCase(redisInstanceName));
    }

    /**
     * 根据实例名称获取该实例对应的redisTemplate
     */
    public StringRedisTemplate getRedisTemplate(String instanceName) {
        return redisTemplates.get(StringUtils.lowerCase(instanceName));
    }

    /**
     * 根据实例名称获取到该实例对应的连接工厂
     */
    public RedisConnectionFactory getRedisConnectionFactory(String instanceName) {
        return redisConnectionFactories.get(StringUtils.lowerCase(instanceName));
    }
}